import math
from typing import List

from algs.common import CableMechanicsData, OilWellData

# 弹性模量
E: float = 4.567e10
# 电缆惯性矩
I: float = 1.49e-11


# 获取深度为 d 时的狗腿度
def get_dog_leg_severity(d: float, _list_: List[OilWellData]) -> float:
    for item in _list_:
        if item.depth == d:
            return item.dog_leg_severity
    print("未查询到该深度对应的狗腿度")


# 获取深度为 d 时的井斜角
def get_inclination(d: float, _list_: List[OilWellData]) -> float:
    for item in _list_:
        if item.depth == d:
            return item.inclination
    print("未查询到该深度对应的井斜角")


# 获取深度为 d 时的井斜角变化率
def get_inclination_rate(d: float, _list_: List[OilWellData]) -> float:
    for item in _list_:
        if item.depth == d:
            return item.inclination_rate
    print("未查询到该深度对应的井斜角变化率")


# 获取深度为 d 时的方位角变化率
def get_azimuth_rate(d: float, _list_: List[OilWellData]) -> float:
    for item in _list_:
        if item.depth == d:
            return item.azimuth_rate
    print("未查询到该深度对应的井方位角变化率")


# 定义词典
bending_moment_dict = {}


# 计算当前深度弯矩
# d 当前深度
# D 井深
def get_bending_moment(d: float, D: float, _list_: List[OilWellData]) -> float:
    # 优先读取词典
    if bending_moment_dict.get(d) is None:
        if d == D:
            return 0
        else:
            result: float = E * I * get_dog_leg_severity(d, _list_)
            bending_moment_dict[d] = result
            return result
    else:
        return bending_moment_dict.get(d)


# 计算轴力
def get_axial_force(d: float, D: float, _list_: List[OilWellData]) -> float:
    return 0.0


# 计算微元段正压力 Nn(d)
# d 当前深度
# space 微元段长度 间隔
# buoyancy factor 浮力系数
def get_incremental_segmental_positive_pressure(d: float,
                                                D: float,
                                                space: float,
                                                _list_: List[OilWellData],
                                                cable: CableMechanicsData,
                                                buoyancy_factor: float) -> float:
    # 定义计算元
    factor_a: float = (get_bending_moment(d - space, D, _list_) + get_bending_moment(d + space, D, _list_) - 2 *
                       get_bending_moment(d, D, _list_)) / math.pow(space, 2)
    factor_b: float = get_dog_leg_severity(d, _list_) * get_axial_force(d - space, D, _list_)
    factor_c: float = cable.cable_tool_line_weight * buoyancy_factor * (
            get_inclination_rate(d, _list_) / get_dog_leg_severity(d, _list_)) * math.sin(
        math.radians(get_inclination(d, _list_)))
    if d < D:
        result = factor_a - factor_b - factor_c
        return result
    else:
        result = factor_a - factor_c
        return result


# "微元段负压力"的英文翻译是 "incremental segmental negative
# pressure"。在石油工业中，这通常是指油井钻探或生产过程中，油井壁与地层之间出现的压力差异，使得地层中的流体（如油、气或水）向油井流动，从而对井筒产生负压力。负压力也称为吸力或负压梯度，这在油井生产和油藏开发中是一个重要的概念。
def get_incremental_segmental_negative_pressure(d: float,
                                                D: float,
                                                space: float,
                                                _list_: List[OilWellData],
                                                cable: CableMechanicsData,
                                                buoyancy_factor: float) -> float:
    result = cable.cable_tool_line_weight * buoyancy_factor * (
            get_azimuth_rate(d, _list_) / get_dog_leg_severity(d, _list_)) * math.sin(
        math.radians(get_inclination(d, _list_)))
    return result


# 计算微元段压力 N(d)
def get_incremental_segmental_pressure(d: float,
                                        D: float,
                                        space: float,
                                        _list_: List[OilWellData],
                                        cable: CableMechanicsData,
                                        buoyancy_factor: float) -> float:
    # 微元段正压
    n_p: float = get_incremental_segmental_positive_pressure(d, D, space, _list_, cable, buoyancy_factor)
    # 微元段负压
    n_n: float = get_incremental_segmental_negative_pressure(d, D, space, _list_, cable, buoyancy_factor)
    # 计算结果
    pow_p: float = math.pow(n_p, 2)
    pow_n: float = math.pow(n_n, 2)
    result = math.sqrt(pow_p + pow_n)
    return result



class FluidResult:
    d_e: float
    a1: float
    a2: float
    a3: float
    v1: float
    v2: float
    v3: float
    r_e: float
    f_m: float
    p_f: float
    tau: float
    f_s: float
    a_t: float
    f_p: float
    c_c: float
    v_vc: float
    p_c: float
    p_l_c: float
    p_e: float
    k: float
    p_l_e: float
    p_l: float
    p_a_long: float
    p_a_short: float
    f_a: float
    f_nw: float
    f_all: float


def get_fluid_resistance_result(data: CableMechanicsData) -> FluidResult:
    result = FluidResult()
    # 求解参数 d_e
    d_e = data.annulus_coefficient * (data.casing_inner_diameter - data.cable_tool_outer_diameter)
    result.d_e = d_e
    # 求解 a1
    a1 = math.pi * math.pow(data.casing_inner_diameter, 2) * 0.25
    result.a1 = a1
    # 求解 a2
    a2 = math.pi * (math.pow(data.casing_inner_diameter, 2) - math.pow(data.cable_tool_outer_diameter, 2)) * 0.25
    result.a2 = a2
    # 求解 a3
    a3 = math.pi * (math.pow(data.casing_inner_diameter, 2) - math.pow(data.cable_outer_diameter, 2)) * 0.25
    result.a3 = a3
    # 求解 v1
    v1 = (data.surface_flow_velocity * data.volume_factor) / a1
    result.v1 = v1
    # 求解 v2
    v2 = (data.surface_flow_velocity * data.volume_factor) / a2
    result.v2 = v2
    # 求解 v3
    v3 = (data.surface_flow_velocity * data.volume_factor) / a3
    result.v3 = v3
    # 求解 r_e
    r_e = (data.drilling_fluid_density * v2 * d_e) / data.hydrodynamic_viscosity
    result.r_e = r_e
    # 求解 f_m
    if r_e <= 2100:
        f_m = 64 / r_e
    else:
        f_m = 0.3164 / math.pow(r_e, 0.25)
    result.f_m = f_m
    # 求解 p_f
    p_f = f_m * data.drilling_fluid_density * v2 * data.cable_tool_length * 0.5 / (data.newton_coefficient * d_e)
    result.p_f = p_f
    # 求解 tau
    tau = (data.casing_inner_diameter - data.cable_tool_outer_diameter) * 0.25 * p_f / data.cable_tool_length
    result.tau = tau
    # 求解 f_s
    f_s = tau * math.pi * data.cable_tool_outer_diameter * data.cable_tool_length
    result.f_s = f_s
    # 求解 delta
    # delta = (data.casing_inner_diameter - data.cable_tool_outer_diameter) * 0.5
    # 求解 e_c
    # e_c = 2 * delta * (data.casing_inner_diameter - data.cable_tool_outer_diameter)
    # 求解 psi
    # if r_e <= 2100:
    #     psi = 1 - 0.072 * e_c * math.pow((data.cable_tool_outer_diameter / data.casing_inner_diameter), 0.8454) - 1.5 * math.pow(e_c, 2) * math.pow((data.cable_tool_outer_diameter / data.casing_inner_diameter), 0.1852) + 0.96 * math.pow(e_c, 3) * math.pow((data.cable_tool_outer_diameter / data.casing_inner_diameter), 0.2527)
    # else:
    #     psi = 1 - 0.048 * e_c * math.pow((data.cable_tool_outer_diameter / data.casing_inner_diameter), 0.8454) - 1.5 * math.pow(e_c, 2) * math.pow((data.cable_tool_outer_diameter / data.casing_inner_diameter), 0.1852) + 0.96 * math.pow(e_c, 3) * math.pow((data.cable_tool_outer_diameter / data.casing_inner_diameter), 0.2527)
    # 求解 p_fecc
    # p_fecc = psi * p_f
    # 求解 a_t
    a_t = math.pi * math.pow(data.cable_tool_outer_diameter, 2) * 0.25
    result.a_t = a_t
    # 求解 f_p
    f_p = p_f * a_t
    result.f_p = f_p
    # 求解 c_c
    c_c = 0.6349 - 0.1697 * (a2 / a1) + 0.5145 * math.pow((a2 / a1), 2)
    result.c_c = c_c
    # 求解 v_vc
    v_vc = data.surface_flow_velocity / (c_c * a2)
    result.v_vc = v_vc
    # 求解 p_c
    p_c = ((0.5 * data.drilling_fluid_density * math.pow(v_vc, 2)) / data.newton_coefficient) * (
            1 - math.pow((c_c * a2 / a1), 2))
    result.p_c = p_c
    # 求解 p_l_c
    p_l_c = math.pow(1 / c_c - 1, 2) * data.drilling_fluid_density * math.pow(v2, 2) * 0.5 / data.newton_coefficient
    result.p_l_c = p_l_c
    # 求解 p_e
    p_e = 0.5 * data.drilling_fluid_density * math.pow(v2, 2) / data.newton_coefficient * (1 - math.pow(a2 / a3, 2))
    result.p_e = p_e
    # 求解 k
    k = math.pow((1 - math.pow(a2 / a3, 2)), 2)
    result.k = k
    # 求解 p_l_e
    p_l_e = k * 0.5 * data.drilling_fluid_density * math.pow(v2, 2) / data.newton_coefficient
    result.p_l_e = p_l_e
    # 求解 p_l
    p_l = 0.5 * data.drilling_fluid_density * math.pow(v3, 2) / data.newton_coefficient * math.pow(
        ((a3 - c_c * a2) / (c_c * a2)), 2)
    result.p_l = p_l
    # 求解 p_a_long
    p_a_long = p_c - p_e + p_l_c + p_l_e
    result.p_a_long = p_a_long
    # 求解 p_a_short
    p_a_short = p_c - p_e + p_l
    result.p_a_short = p_a_short
    # 求解 f_a
    f_a = p_a_long * a_t
    result.f_a = f_a
    # 求解 f_nw
    f_nw = (f_s + f_p + f_a) / data.cable_tool_length
    result.f_nw = f_nw
    # 求解 f_all
    f_all = f_s + f_p + f_a
    result.f_all = f_all

    return result


def get_cable_axial_force_result(data: CableMechanicsData, welldata: OilWellData) -> float:
    # 迭代时需要将狗腿度由角度转换为弧度，并且第一次迭代（初始时）的正压力和轴力为0，即第一次迭代时 dog_leg_severity(i+1) * t(i+1) =0

    # 狗腿度 角度转弧度
    dog_leg_severity = math.radians(welldata.dog_leg_severity / 30)


if __name__ == '__main__':
    print(E)
    print(I)
    # data = CableMechanicsData()
    # data.cable_tool_outer_diameter = 0.09
    # data.drilling_fluid_density = 1300
    # data.surface_flow_velocity = 0.00001
    # data.casing_inner_diameter = 0.23
    # data.newton_coefficient = 1
    # data.cable_tool_elastic_modulus = 45.67 * math.pow(10, 9)
    # data.cable_tool_line_weight = 6.899
    # data.hydrodynamic_viscosity = 0.45 * math.pow(10, -3)
    # data.cable_tool_length = 3400
    # data.cable_tool_density = 5142
    # data.volume_factor = 1.41
    # data.annulus_coefficient = 1
    # data.friction_coefficient = 0.28
    # data.cable_tool_inertia_moment = 1.49 * math.pow(10, -9)
    # data.cable_outer_diameter = 0.0132
    # data.cable_material_allowable_stress = 100
    # data.microelement_segment_length = 5
    # data.safety_factor = 2.5
    #
    # fluid_result = get_fluid_resistance_result(data)
    # print('===流体阻力值为===')
    # print(JsonUtil.obj2str(fluid_result))
